/* Copyright (c) 2009, Antonie Jovanoski
 *	
 * All rights reserved.
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Contact e-mail: Antonie Jovanoski <minimoog77@gmail.com>
 */

#include <QtDebug>
#include <QtAlgorithms>
#include <QMessageBox>
#include "qtwitdget.h"
#include "userpassdialog.h"
#include "qtwitverifycredentials.h"
#include "shortenedurl.h"

QTwitdget::QTwitdget(QWidget *parent)
	:	QWidget(parent), 
		m_friendsTimeline(new QTwitFriendsTimeline(this)),
		m_twitUpdate(new QTwitUpdate(this)),
		m_twitDestroy(new QTwitDestroy(this)),
		m_imageDownloader(new ImageDownloader(this))
{
	ui.setupUi(this);
	ui.groupWidget->hide();

	qApp->setStyleSheet("StatusWidget { border: 2px solid darkgray; border-radius: 10px; padding: 0 8px; background: white; }");

	//read last used username
	QSettings settings("QTwitdget", "QTwitdget");
	m_username = settings.value("LastUsername").toString();

	//should be programmable
	m_maxStatuses = 200;

	connect(ui.userpassButton, SIGNAL(clicked()), SLOT(userpassButtonClicked()));
	connect(ui.updateButton, SIGNAL(clicked()), SLOT(updateButtonClicked()));
	connect(ui.backButton, SIGNAL(clicked()), SLOT(backButtonClicked()));
	connect(ui.forwardButton, SIGNAL(clicked()), SLOT(forwardButtonClicked()));
	connect(m_friendsTimeline, SIGNAL(finished()), SLOT(finishedFriendsTimeline()));
	connect(m_twitDestroy, SIGNAL(destroyed(int)), SLOT(statusDestroyed(int)));
	connect(m_imageDownloader, SIGNAL(finished()), SLOT(finishedDownloadImages()));
	connect(ui.updateEdit, SIGNAL(overLimit(bool)), ui.updateButton, SLOT(setDisabled(bool)));
	connect(ui.updateEdit, SIGNAL(returnPressed()), ui.updateButton, SLOT(click()));

	ui.updateEdit->setLimit(140);

	m_scrollAreaContents = new QWidget();
	m_verticalLayout = new QVBoxLayout(m_scrollAreaContents);
	ui.scrollArea->setWidget(m_scrollAreaContents);

	ui.backButton->setEnabled(false);
	ui.forwardButton->setEnabled(false);

	m_statusWidgetsPerPage = 20; //should be programmable
	m_currentPage = 0;
	m_initialUpdate = true;

	//set StatusWidgets
	setupStatusWidgets();

	userpassButtonClicked();

	setupTrayIcon();
}

void QTwitdget::setupStatusWidgets()
{
	for(int i = 0; i < m_statusWidgetsPerPage; ++i){
		StatusWidget *sw = new StatusWidget(m_scrollAreaContents);
		m_verticalLayout->addWidget(sw);
		m_statusWidgets.append(sw);
		connect(sw, SIGNAL(replyRequest(const QString&, int)), m_twitUpdate, SLOT(setUpdate(const QString&, int)));
		connect(sw, SIGNAL(deleteRequest(int)), m_twitDestroy, SLOT(deleteStatus(int)));
	}

	m_scrollAreaContents->adjustSize();
}

void QTwitdget::updateStatusWidgets()
{
	//build url image list for downloading for current page
	QList<QUrl> urlsImages;
	
	int ns = 0;
	QList<QTwitStatus>::const_iterator i = m_statuses.begin() + m_statusWidgetsPerPage * m_currentPage;
	while(i != m_statuses.end() && ns < m_statusWidgetsPerPage){

		QTwitStatus status = *i;

		urlsImages << status.profileImageUrl();

		//set statuses
		StatusWidget *sw = m_statusWidgets.at(ns);
		sw->setText(status.text());
		sw->setScreenName(status.screenName());
		sw->setSource(status.source());
		sw->setCreated(status.created());
		sw->setStatusId(status.id());

		if(status.screenName() == m_username){
			sw->setEnabledReplyButton(false);
			sw->setEnabledDeleteButton(true);
		} else {
			sw->setEnabledReplyButton(true);
			sw->setEnabledDeleteButton(false);
		}

		++i;
		++ns;
	}

	if(ns < m_statusWidgetsPerPage){
		for(int j = ns + 1; j < m_statusWidgetsPerPage; ++j){
			StatusWidget *sw = m_statusWidgets.at(j);
			sw->setText(QString());
			sw->setScreenName(QString());
			sw->setSource(QString());
			sw->setCreated(QDateTime());
			sw->setStatusId(0);
			sw->setEnabledReplyButton(false);
			sw->setEnabledDeleteButton(false);
			sw->setProfileImagePixmap(QPixmap());
		}
	}

	//download/load images
	m_imageDownloader->downloadImages(urlsImages);
}

void QTwitdget::userpassButtonClicked()
{
	UserPassDialog upd(this);
	upd.setUsername(m_username);
	if(!m_username.isEmpty())
		upd.setPasswordEditFocut();

	if(QDialog::Accepted == upd.exec()){

		//verify credentials
		QTwitVerifyCredentials *vc = new QTwitVerifyCredentials;
		connect(vc, SIGNAL(finished(bool)), SLOT(finishedVerifying(bool)));
		vc->setUsername(upd.username());
		vc->setPassword(upd.password());
		m_verified = false;
		vc->verify();
		//block until is verified
		while(!m_verified) 
			qApp->processEvents();

		if(!m_userpassValid){
			delete vc;
			QMessageBox::warning(this, tr("Credentials error!"), tr("Username or password invalid"));
			return;
		}

		delete vc;

		setUserPass(upd.username(), upd.password());

		//store last used username
		QSettings settings("QTwitdget", "QTwitdget");
		settings.setValue("LastUsername", upd.username());

		//start update timer
		//TODO: What about "old timer"?
		QTimer *timer = new QTimer(this);
		connect(timer, SIGNAL(timeout()), SLOT(updateTimeline()));
		timer->start(60000);

		updateTimeline();
	}
}

void QTwitdget::backButtonClicked()
{
	m_currentPage -= 1;

	if(m_currentPage == 0)
		ui.backButton->setEnabled(false);

	ui.forwardButton->setEnabled(true);

	updateStatusWidgets();
}

void QTwitdget::forwardButtonClicked()
{
	m_currentPage += 1;

	ui.backButton->setEnabled(true);

	if(m_statusWidgetsPerPage * (m_currentPage + 1) > m_statuses.count())
		ui.forwardButton->setEnabled(false);

	updateStatusWidgets();
}

void QTwitdget::updateTimeline()
{
	if(m_initialUpdate)	//first update, get first 200 statuses, should be programmable
		m_friendsTimeline->update(QDateTime(), 0, 200, 0);
	else
		//get statuses more recent than last status 
		m_friendsTimeline->update(QDateTime(), m_statuses.at(0).id(), 0, 0);
}

void QTwitdget::setUserPass(const QString &username, const QString &password)
{
	m_friendsTimeline->setUsername(username);
	m_friendsTimeline->setPassword(password);
	m_twitUpdate->setUsername(username);
	m_twitUpdate->setPassword(password);
	m_twitDestroy->setUsername(username);
	m_twitDestroy->setPassword(password);
	m_username = username;
	m_password = password;
}

void QTwitdget::updateButtonClicked()
{
	if(!ui.updateEdit->toPlainText().isEmpty()){
		//trim to 140 characters
		QString updateText = ui.updateEdit->toPlainText().left(140);
		m_twitUpdate->setUpdate(updateText);
		ui.updateEdit->clear();
	}
}

void QTwitdget::finishedFriendsTimeline()
{
	QList<QTwitStatus> lastStatuses = m_friendsTimeline->getStatuses();

	if(lastStatuses.isEmpty())
		return;

	//prepend last statuses to statuses
	QListIterator<QTwitStatus> iter(lastStatuses);
	iter.toBack();
	while(iter.hasPrevious())
		m_statuses.prepend(iter.previous());

	if(m_initialUpdate)
		if(m_statuses.count() > m_statusWidgetsPerPage)
			ui.forwardButton->setEnabled(true);

	updateStatusWidgets();

	m_initialUpdate = false;
}

void QTwitdget::finishedDownloadImages()
{
	QHash<QString, QImage> images = m_imageDownloader->getImages();

	for(int i = 0; i < m_statusWidgetsPerPage; ++i){
		StatusWidget *sw = m_statusWidgets.at(i);

		int atStatus = m_currentPage * m_statusWidgetsPerPage + i;
		
		if(atStatus < m_statuses.count()){
			QImage img = images.value(m_statuses.at(atStatus).profileImageUrl());
			sw->setProfileImagePixmap(QPixmap::fromImage(img));
		}
	}
}

void QTwitdget::setupTrayIcon()
{
	minimizeAction = new QAction(tr("Mi&nimize"), this);
	connect(minimizeAction, SIGNAL(triggered()), SLOT(hide()));

	restoreAction = new QAction(tr("&Restore"), this);
	connect(restoreAction, SIGNAL(triggered()), SLOT(showNormal()));

	quitAction = new QAction(tr("&Quit"), this);
	connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));

	trayIconMenu = new QMenu(this);
	trayIconMenu->addAction(minimizeAction);
	trayIconMenu->addAction(restoreAction);
	trayIconMenu->addSeparator();
	trayIconMenu->addAction(quitAction);

	trayIcon = new QSystemTrayIcon(this);
	trayIcon->setIcon(QIcon(":/images/twitter_32.ico"));
	trayIcon->setContextMenu(trayIconMenu);
	trayIcon->show();

	connect(trayIcon, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
		SLOT(trayIconActivated(QSystemTrayIcon::ActivationReason)));
}

void QTwitdget::trayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
	switch(reason){
		case QSystemTrayIcon::Trigger:
		case QSystemTrayIcon::DoubleClick:
			showNormal();
			break;
		default:
			;
	}
}

void QTwitdget::finishedVerifying(bool valid)
{
	m_userpassValid = valid;

	m_verified = true;
}

void QTwitdget::statusDestroyed(int id)
{
	//remove status
	QMutableListIterator<QTwitStatus> i(m_statuses);
	while(i.hasNext()){
		QTwitStatus ts = i.next();
		if(ts.id() == id){
			i.remove();
			break;
		}
	}

	updateStatusWidgets();
}

void QTwitdget::closeEvent(QCloseEvent *e)
{
	hide();
	e->ignore();
}